from django.template import loader, RequestContext
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth import login
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.core.urlresolvers import reverse

from models import Yubikey
from forms import LoginForm, PasswordForm

# Ask for the user password after the token
YUBIKEY_USE_PASSWORD = getattr(settings, 'YUBIKEY_USE_PASSWORD', True)

# Session key name
YUBIKEY_SESSION_USER = getattr(settings, 'YUBIKEY_SESSION_USER', 'yubidjango_user')

# Session key name for password attempts
YUBIKEY_ATTEMPT_COUNTER = getattr(settings, 'YUBIKEY_ATTEMPT_COUNTER', 'yubidjango_counter')

# Maximum password attempts per token to avoid brute force attacks when someone
# gets a valid token and session cookie.
YUBIKEY_PASSWORD_ATTEMPTS = getattr(settings, 'YUBIKEY_PASSWORD_ATTEMPTS', 3)

def login_view(request, template='yubidjango/login.html', redirect_url=None):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            if YUBIKEY_USE_PASSWORD:
                request.session[YUBIKEY_SESSION_USER] = form.user
                # Reset attempt counter when we accept a new token
                request.session[YUBIKEY_ATTEMPT_COUNTER] = 1
                return HttpResponseRedirect(reverse('yubidjango-password'))
            else:
                login(request, form.user)
                return HttpResponseRedirect(redirect_url or settings.LOGIN_REDIRECT_URL)
        else:
            # Empty the fields, we don't want to redisplay the user input
            form.data = {}
    else:
        form = LoginForm()

    templ = loader.get_template(template)
    cont = RequestContext(request, {'form': form,})
    return HttpResponse(templ.render(cont))

def password_view(request, template='yubidjango/password.html', redirect_url=None):
    if not request.session.get(YUBIKEY_SESSION_USER) or not request.session.get(YUBIKEY_ATTEMPT_COUNTER):
        return HttpResponseRedirect(reverse('yubidjango-login'))

    if request.method == 'POST':
        form = PasswordForm(request.POST, user=request.session[YUBIKEY_SESSION_USER])
        if form.is_valid():
            login(request, request.session[YUBIKEY_SESSION_USER])
            # We catch key errors in case someone "double clicks" on the submit button
            try:
                del(request.session[YUBIKEY_SESSION_USER])
            except KeyError:
                pass
            try:
                del(request.session[YUBIKEY_ATTEMPT_COUNTER])
            except KeyError:
                pass
            return HttpResponseRedirect(redirect_url or settings.LOGIN_REDIRECT_URL)
        else:
            # Empty the fields, we don't want to redisplay the user input
            form.data = {}

            # Limit the number of password attempts per token
            request.session[YUBIKEY_ATTEMPT_COUNTER] += 1
            if request.session[YUBIKEY_ATTEMPT_COUNTER] > YUBIKEY_PASSWORD_ATTEMPTS:
                del(request.session[YUBIKEY_SESSION_USER])
                del(request.session[YUBIKEY_ATTEMPT_COUNTER])
                return HttpResponseRedirect(reverse('yubidjango-login')) 
    else:
        form = PasswordForm(user=request.session[YUBIKEY_SESSION_USER])

    templ = loader.get_template(template)
    cont = RequestContext(request, {'form': form,})
    return HttpResponse(templ.render(cont))
